﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Actuals.CoreDomain.Business;
using Actuals.CoreDomain;
using Actuals.CoreDomain.Data;
using Actuals.Data;

namespace Actuals.Business
{
    public class BusinessNoOfDays : IBusinessNoOfDays
    {
        #region IBusinessNoOfDays Members

        public double CaculateNoOfBusinessDays(DateTime startDate, DateTime endDate)
        {
            return CalculateBDay(startDate, endDate, 5, 0);
        }

        public static double CalculateBDay(
    DateTime startDate,
    DateTime EndDate,
    int NoOfDayWeek, /* No of Working Day per week*/
    int DayType
)
        {
            double iWeek, iDays, isDays, ieDays;
            //* Find the number of weeks between the dates. Subtract 1 */

            // since we do not want to count the current week. * /

            iWeek = DateDiff("ww", startDate, EndDate) - 1;
            iDays = iWeek * NoOfDayWeek;
            //

            if (NoOfDayWeek == 5)
            {
                //-- If Saturday, Sunday is holiday

                if (startDate.DayOfWeek == DayOfWeek.Saturday)
                    isDays = 7 - (int)startDate.DayOfWeek;
                else
                    isDays = 7 - (int)startDate.DayOfWeek - 1;
            }
            else
            {
                //-- If Sunday is only <st1:place>Holiday</st1:place>

                isDays = 7 - (int)startDate.DayOfWeek;
            }
            //-- Calculate the days in the last week. These are not included in the

            //-- week calculation. Since we are starting with the end date, we only

            //-- remove the Sunday (datepart=1) from the number of days. If the end

            //-- date is Saturday, correct for this.

            if (NoOfDayWeek == 5)
            {
                if (EndDate.DayOfWeek == DayOfWeek.Saturday)
                    ieDays = (int)EndDate.DayOfWeek - 2;
                else if (EndDate.DayOfWeek == DayOfWeek.Monday)
                    ieDays = 1;
                else
                    ieDays = (int)EndDate.DayOfWeek;
            }
            else
            {
                ieDays = (int)EndDate.DayOfWeek - 1;
            }
            //-- Sum everything together.

            iDays = iDays + isDays + ieDays;
        
                return iDays;
           
        }

        /// <summary>

        /// Calculate weeks between starting date and ending date

        /// </summary>

        /// <param name="stdate"></param>

        /// <param name="eddate"></param>

        /// <returns></returns>


        public static int GetWeeks(DateTime stdate, DateTime eddate)
        {

            TimeSpan t = eddate - stdate;
            int iDays;

            if (t.Days < 7)
            {
                if (stdate.DayOfWeek > eddate.DayOfWeek)
                    return 1; //It is accross the week 


                else
                    return 0; // same week

            }
            else
            {
                iDays = t.Days - 7 + (int)stdate.DayOfWeek;
                int i = 0;
                int k = 0;

                for (i = 1; k < iDays; i++)
                {
                    k += 7;
                }

                if (i > 1 && eddate.DayOfWeek != DayOfWeek.Sunday) i -= 1;
                return i;
            }
        }


        /// <summary>

        /// Mimic the Implementation of DateDiff function of VB.Net.

        /// Note : Number of Year/Month is calculated

        ///        as how many times you have crossed the boundry.

        /// e.g. if you say starting date is 29/01/2005

        ///        and 01/02/2005 the year will be 0,month will be 1.

        /// 


        /// </summary>

        /// <param name="datePart">specifies on which part 

        ///   of the date to calculate the difference </param>

        /// <param name="startDate">Datetime object containing

        ///   the beginning date for the calculation</param>

        /// <param name="endDate">Datetime object containing

        ///   the ending date for the calculation</param>

        /// <returns></returns>


        public static double DateDiff(string datePart,
                      DateTime startDate, DateTime endDate)
        {

            //Get the difference in terms of TimeSpan

            TimeSpan T;

            T = endDate - startDate;

            //Get the difference in terms of Month and Year.

            int sMonth, eMonth, sYear, eYear;
            sMonth = startDate.Month;
            eMonth = endDate.Month;
            sYear = startDate.Year;
            eYear = endDate.Year;
            double Months, Years = 0;
            Months = eMonth - sMonth;
            Years = eYear - sYear;
            Months = Months + (Years * 12);

            switch (datePart.ToUpper())
            {
                case "WW":
                case "DW":
                    return (double)GetWeeks(startDate, endDate);
                case "MM":
                    return Months;
                case "YY":
                case "YYYY":
                    return Years;
                case "QQ":
                case "QQQQ":
                    //Difference in Terms of Quater

                    return Math.Ceiling((double)T.Days / 90.0);
                case "MI":
                case "N":
                    return T.TotalMinutes;
                case "HH":
                    return T.TotalHours;
                case "SS":
                    return T.TotalSeconds;
                case "MS":
                    return T.TotalMilliseconds;
                case "DD":
                default:
                    return T.Days;
            }
        }

        #endregion
    }
}
